package mirrormonkey.core.member;

import java.lang.reflect.Constructor;

import mirrormonkey.core.annotations.NamedClientSideConstructor;
import mirrormonkey.framework.entity.StaticEntityData;
import mirrormonkey.framework.entity.StaticEntityData.MemberDataKey;
import mirrormonkey.framework.entity.SyncEntity;
import mirrormonkey.framework.member.DynamicMemberData;
import mirrormonkey.framework.member.StaticMemberData;
import mirrormonkey.framework.parameter.ParameterInterpreter;
import mirrormonkey.framework.parameter.ParameterInterpreterUtil;

public class ConstructorData implements StaticMemberData {

	protected final MemberDataKey key;

	protected final int id;

	protected final ParameterInterpreter[] interpreters;

	protected final Constructor<?> constr;

	private StaticEntityData staticData;

	public ConstructorData(int id, ParameterInterpreter[] interpreters,
			Constructor<?> constr, NamedClientSideConstructor nameAnnot) {
		if (nameAnnot == null) {
			key = new PresentKey(this);
		} else {
			key = new PresentNamedKey(this, nameAnnot.value());
		}
		this.id = id;
		this.interpreters = interpreters;
		this.constr = constr;
	}

	public Object[] interpretParams(Object[] params) {
		Object[] result = new Object[params.length];
		int i = 0;
		for (ParameterInterpreter pi : interpreters) {
			result[i] = pi.extractData(params[i]);
			i++;
		}
		return result;
	}

	public Object[] packParams(Object[] params) {
		return ParameterInterpreterUtil.packParams(params, interpreters);
	}

	public SyncEntity newEntity(Object[] constrParams) {
		try {
			return (SyncEntity) constr
					.newInstance(interpretParams(constrParams));
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean equals(Object o) {
		if (!ConstructorData.class.isInstance(o)) {
			return false;
		}
		ConstructorData cd = (ConstructorData) o;
		return cd.id == id;
	}

	@Override
	public MemberDataKey getMemberKey() {
		return key;
	}

	public String getConnectedClassName() {
		return staticData.connectedClass.getName();
	}

	public int getId() {
		return id;
	}

	@Override
	public DynamicMemberData createDynamicData() {
		return null;
	}

	@Override
	public void setStaticEntityData(StaticEntityData staticData) {
		this.staticData = staticData;
	}

	public String getLocalClassName() {
		return staticData.localClass.getName();
	}

	@Override
	public String toString() {
		return "[" + super.toString() + ": static=" + staticData + "]";
	}

}
